package modelo.esclavo1;

import java.rmi.RemoteException;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

import util.AgregadorRMI;
import util.IPGetter;

import controlador.buzones.BuzonIface;
import controlador.buzones.Buzon;
import controlador.buzones.Mensaje;
import controlador.buzones.MessageTypes;
import controlador.io.Config;

/**
 * Clase que representa el automata de control de la cinta de elaboracion de ejes/engranajes.
 * 
 * @version 1.0
 * @author Globex Inc. 
 */
public class Automata1 {

	// TODO Schedule for removal
	public Robot1 robot1;

	//public int numEjes;
	//public int numEngranajes;

	/**Variable que indica si la cinta esta activada*/
	private boolean cintaEjesActivada; // true en marcha, false parada

	private boolean cintaEngranajesActivada; // true en marcha, false parada



	/* Sensores */

	private boolean sensorCintaEjes;

	private boolean sensorCintaEngranajes;

	private boolean sensorPresenciaEstacionMontaje;

	/* Estados */

	boolean ejeEnEstacion;
	boolean engranajeEnEstacion;
	boolean accionamientoHidraulicoActivado;
	boolean conjuntoMontadoFinalizado;
	boolean transitarEstacion;

	/**Indica si el eje/engranaje esta en la cinta*/
	private boolean EjeEnCinta;
	private boolean EngranajeEnCinta;

	/**Almacena el estado actual de la cinta ejes*/
	private int estadoActualCintaEjes;

	/**Almacena el estado actual de la cinta engranajes*/
	private int estadoActualCintaEngranajes;

	/**Almacena el estado actual de la estacion de montaje*/
	private int estadoActualEstacionMontaje;

	/**Almacena el estado actual del robot1*/
	private int estadoActualRobot1;

	/**Indica el instante inicial del eje/engranaje en la cinta*/
	private long instanteInicialEje;
	private long instanteInicialEngranaje;

	/**Indica si el automata esta arrancado*/
	private boolean automataArrancado;

	/**Indica si se ha pulsado la parada normal*/
	private boolean paradaNormalInicio;
	private boolean paradaNormalFin;

	/**Indica si se ha pulsado la parada de emergencia*/
	private boolean paradaEmergencia;

	/**Indica el instante en el que se inicia el accionamiento hidraulico*/
	private long tiempoInicioMontaje;

	/**Indica el tiempo que se termina el accionamiento hidraulico*/
	private long tiempoParadoMontaje;

	private long tiempoDeMontaje;
	/* Suministro */
	/**Indica la cantidad restante de ejes*/
	private int ejesRestante;

	/**Indica la cantidad restante de engranajes*/
	private int engranajesRestante;

	/**Indica el numero de conjuntos hechos*/
	private int conjuntosHechos;

	// Posiciones
	/**Indica la posicionActual del eje en la cinta*/
	private float posicionActualEje;
	public Vector<Float> posicionesEjes;
	public Vector<Long> instanteEjes;
	/**Indica la posicionActual del engranaje en la cinta*/
	private float posicionActualEngranaje;
	public Vector posicionesEngranajes;
	public Vector<Long> instanteEngranajes;

	/* CONFIGURACION */
	/**Representa el ciclo de reloj*/
	private long cicloReloj; // en milisegundos

	/**Almacena la velocidad de la cinta*/
	private float velocidadCintaEjes;// en metros/minuto

	private int capacidadEjes;
	private int capacidadEngranajes;

	/**Almacena la longitud de cinta*/
	private float longitudCintaEjes;// metros

	/**Almacena la velocidad de la cinta*/
	private float velocidadCintaEngranajes;// en metros/minuto

	/**Almacena la longitud de cinta*/
	private float longitudCintaEngranajes;// metros

	/**ejes/engranajes que quedan por hacer antes de parar la cinta de manera normal*/
	int conjuntosPendientesParadaNormal;

	/**conjuntos hechos antes de parar la cinta de manera normal*/
	int conjuntosSoltadosParadaNormal;

	int diferenciaEjes;
	int diferenciaEngranajes;

	boolean insertarEjeEngranaje;

	boolean primerRun;

	/**Buzones de comunicaci&ocute;n*/
	private BuzonIface _miBuzon;
	private BuzonIface _buzonMaestro;
	
	private Logger _logger = Logger.getLogger("automata.esclavo1");

	/**
	 * Constructor del Automata 1 que inicializa el valor de todas las variables.
	 */
	public Automata1() {
		robot1=new Robot1();
		//numEjes=4;
		//numEngranajes=4;
		cintaEjesActivada = false; // true en marcha, false parada
		cintaEngranajesActivada = false; // true en marcha, false parada
		/* Sensores */
		sensorCintaEjes = false;// true, esta detectando
		sensorCintaEngranajes = false;// true, esta detectando
		sensorPresenciaEstacionMontaje=false;


		/* Suministro*/ 
		ejesRestante = capacidadEjes;
		engranajesRestante = capacidadEngranajes;
		conjuntosHechos = 0;

		/* Estados */
		ejeEnEstacion = false;
		engranajeEnEstacion = false;
		accionamientoHidraulicoActivado=false;
		conjuntoMontadoFinalizado=false;
		EjeEnCinta=false;
		EngranajeEnCinta=false;
		transitarEstacion=false;

		estadoActualRobot1 = 0;
		estadoActualCintaEjes=1;
		estadoActualCintaEngranajes=1;
		estadoActualEstacionMontaje=1;
		instanteInicialEje = 0;
		instanteInicialEngranaje = 0;

		tiempoInicioMontaje = 0;
		tiempoParadoMontaje = 0;

		posicionesEjes=new Vector<Float>();
		instanteEjes=new Vector<Long>();
		posicionesEngranajes=new Vector<Float>();
		instanteEngranajes=new Vector<Long>();
		/*
		velocidadCintaEjes=40;
		velocidadCintaEngranajes=20;
		longitudCintaEjes=10;
		longitudCintaEngranajes=10;
		capacidadEjes=50;
		capacidadEngranajes=50;
		tiempoDeMontaje=3000;
		 */

		automataArrancado = false;
		paradaNormalInicio = false;
		paradaNormalFin=false;
		paradaEmergencia = false;

		conjuntosPendientesParadaNormal=0;
		conjuntosSoltadosParadaNormal=0;

		diferenciaEjes=0;
		diferenciaEngranajes=0;

		insertarEjeEngranaje=false;

		HashMap<String, String> conf_tmp = Config.read("esclavo1.conf");
		try {
			_miBuzon = new Buzon();
			_miBuzon.registrar(Integer.parseInt(conf_tmp.get("localPort")), conf_tmp.get("localID"));
		} catch (Exception e) {
			_logger.log(Level.SEVERE,"" , e.getStackTrace());
			System.exit(-1);
		}

		_logger.info("Obteniendo buzon del maestro");
		while(_buzonMaestro == null) {
			try {
				_buzonMaestro = (BuzonIface) AgregadorRMI.obtenerRemoto(conf_tmp.get("masterHost"), Integer.parseInt(conf_tmp.get("masterPort")), conf_tmp.get("masterID"));
			} catch (Exception e) {
				//e.printStackTrace();
				_logger.log(Level.WARNING,"", e.getStackTrace());
			}
		}
		_logger.info("Obtenido buzon del maestro");

		HashMap<String, String> content = new HashMap<String, String>();
		content.put("ip", IPGetter.getIP());
		content.put("puerto", conf_tmp.get("localPort"));
		content.put("id", conf_tmp.get("localID"));
		enviarMensaje(MessageTypes.BEFRIEND, content);

		primerRun=false;
	}

	/*public Automata1(boolean useless) {

		//PropertyConfigurator.configure("loggerAUT1.properties");
		robot1=new Robot1();
		//logger = Logger.getLogger(Automata1.class);
		numEjes=4;
		numEngranajes=4;

		cintaEjesActivada = false; // true en marcha, false parada
		cintaEngranajesActivada = false; // true en marcha, false parada
		// Sensores
		sensorCintaEjes = false;// true, esta detectando
		sensorCintaEngranajes = false;// true, esta detectando
		sensorPresenciaEstacionMontaje=false;


		// Suministro 
		ejesRestante = capacidadEjes;
		engranajesRestante = capacidadEngranajes;
		conjuntosHechos = 0;

		// Estados
		ejeEnEstacion = false;
		engranajeEnEstacion = false;
		accionamientoHidraulicoActivado=false;
		conjuntoMontadoFinalizado=false;
		EjeEnCinta=false;
		EngranajeEnCinta=false;
		transitarEstacion=false;

		estadoActualRobot1 = 0;
		estadoActualCintaEjes=1;
		estadoActualCintaEngranajes=1;
		estadoActualEstacionMontaje=1;
		instanteInicialEje = 0;
		instanteInicialEngranaje = 0;

		tiempoInicioMontaje = 0;
		tiempoParadoMontaje = 0;

		posicionesEjes=new Vector<Float>();
		instanteEjes=new Vector<Long>();
		posicionesEngranajes=new Vector<Float>();
		instanteEngranajes=new Vector<Long>();
		/ *
		velocidadCintaEjes=40;
		velocidadCintaEngranajes=20;
		longitudCintaEjes=10;
		longitudCintaEngranajes=10;
		capacidadEjes=50;
		capacidadEngranajes=50;
		tiempoDeMontaje=3000;
		 * /

		automataArrancado = false;
		paradaNormalInicio = false;
		paradaNormalFin=false;
		paradaEmergencia = false;

		conjuntosPendientesParadaNormal=0;
		conjuntosSoltadosParadaNormal=0;

		diferenciaEjes=0;
		diferenciaEngranajes=0;

		insertarEjeEngranaje=false;
		primerRun=false;

		// PRUEBA HASHMAP

		HashMap<String, String> param=new HashMap<String, String>();
		param.put("cicloReloj", "1000");
		param.put("velocidadEjes", "40");
		param.put("longitudEjes", "10");
		param.put("capacidadEjes", "50");
		param.put("velocidadEngranajes", "40");
		param.put("longitudEngranajes", "10");
		param.put("capacidadEngranajes", "50");
		param.put("tiempoMontaje", "3");
		param.put("tiempoRecEng", "3000");
		param.put("tiempoRecEje", "3000");
		param.put("tiempoTransEng", "3000");
		param.put("tiempoTransEje", "3000");
		param.put("tiempoTransConj", "3000");

		this.configurar(param);
		robot1.configurar(param);
	}*/

	public void inicializar(){
		// TODO Chumo: Why
		//numEjes=4;
		// TODO Chumo: Why?
		//numEngranajes=4;

		cintaEjesActivada = false; // true en marcha, false parada
		cintaEngranajesActivada = false; // true en marcha, false parada
		/* Sensores */
		sensorCintaEjes = false;// true, esta detectando
		sensorCintaEngranajes = false;// true, esta detectando
		sensorPresenciaEstacionMontaje=false;


		/* Suministro*/ 
		ejesRestante = capacidadEjes;
		engranajesRestante = capacidadEngranajes;
		conjuntosHechos = 0;

		/* Estados */
		ejeEnEstacion = false;
		engranajeEnEstacion = false;
		accionamientoHidraulicoActivado=false;
		conjuntoMontadoFinalizado=false;
		EjeEnCinta=false;
		EngranajeEnCinta=false;

		estadoActualRobot1 = 0;
		estadoActualCintaEjes=1;
		estadoActualCintaEngranajes=1;
		estadoActualEstacionMontaje=1;
		instanteInicialEje = 0;
		instanteInicialEngranaje = 0;

		tiempoInicioMontaje = 0;
		tiempoParadoMontaje = 0;

		posicionesEjes=new Vector<Float>();
		instanteEjes=new Vector<Long>();
		posicionesEngranajes=new Vector<Float>();
		instanteEngranajes=new Vector<Long>();
		/*
		velocidadCintaEjes=40;
		velocidadCintaEngranajes=20;
		longitudCintaEjes=10;
		longitudCintaEngranajes=10;
		capacidadEjes=50;
		capacidadEngranajes=50;
		tiempoDeMontaje=3000;
		 */

		automataArrancado = false;
		paradaNormalInicio = false;
		paradaNormalFin=false;
		paradaEmergencia = false;
		
		conjuntosPendientesParadaNormal=0;
		conjuntosSoltadosParadaNormal=0;

		diferenciaEjes=0;
		diferenciaEngranajes=0;
		insertarEjeEngranaje=false;

		primerRun=false;
	}

	/**
	 * Metodo que envia mensajes al buzon maestro
	 * 
	 * 
	 */
	private void enviarMensaje(MessageTypes type, HashMap<String, String> content) {
		Mensaje msj = new Mensaje();
		msj.set_type(type);
		msj.set_source("esclavo1");
		msj.set_target("master");
		msj.set_message(content);

		try{
			_buzonMaestro.encolar(msj);
		}catch (Exception e) {
			_logger.log(Level.SEVERE, "Error al enviar mensaje "+type+" al maestro", e.getStackTrace());
		}
	}
	/**
	 * Metodo que recibe mensajes del automata maestro
	 * 
	 * 
	 */
	private Mensaje recibirMensaje(){
		Mensaje msj = null;
		try {
			msj = _miBuzon.desencolar();
		} catch (Exception e) {
			_logger.info("No hay mensajes en la cola");
			msj = null;
		}
		return msj;
	}

	/**
	 * Metodo que configura los parametros procedentes del aut&oacute;mata maestro
	 * 
	 * @param param es el hashmap de parametros
	 */
	private void configurar(HashMap<String, String> param) {

		/* Parametros de configuracion */
		cicloReloj = Long.parseLong(param.get("cicloReloj"));
		velocidadCintaEjes = Float.parseFloat(param.get("velocidadEjes"));
		velocidadCintaEngranajes = Float.parseFloat(param.get("velocidadEngranajes"));
		longitudCintaEjes = Float.parseFloat(param.get("longitudEjes"));
		longitudCintaEngranajes = Float.parseFloat(param.get("longitudEngranajes"));

		capacidadEjes = Integer.parseInt(param.get("capacidadEjes"));

		capacidadEngranajes = Integer.parseInt(param.get("capacidadEngranajes"));
		tiempoDeMontaje = Integer.parseInt(param.get("tiempoMontaje"));

		// TODO Chumo: Why?
		if (!paradaNormalInicio) {
			ejesRestante = capacidadEjes;
			engranajesRestante = capacidadEngranajes;
		}

		paradaEmergencia=false;
		paradaNormalInicio=false;
		paradaNormalFin=false;

		conjuntosPendientesParadaNormal=0;
		conjuntosSoltadosParadaNormal=0;
	}

	/**
	 * Metodo que rellena el desposito de ejes
	 */
	/*private void rellenarDespositoEjes() {
		ejesRestante = capacidadEjes;
	}*/

	/**
	 * Metodo que rellena el desposito de engranajes
	 */
	/*private void rellenarDespositoEngranajes() {
		engranajesRestante = capacidadEngranajes;
	}*/

	/**
	 * Metodo que devuelve la posicion del eje en la cinta.
	 * 
	 * @return devuelve la posicion.
	 */
	private float obtenerPosicionEje() {
		long instanteActual = System.currentTimeMillis();

		//Se calcula el tiempo total del eje/engranaje en la cinta en segundos
		float tiempoTotal = ((instanteActual - instanteInicialEje ) / 1000);
		
		// La velocidad de la cinta esta en metros/minuto
		float posicion = (velocidadCintaEjes * tiempoTotal) / 60;
		// la posicion se calcula a partir de la velocidad de la cinta y el tiempo que ha estado el eje/engranaje en la misma

		if (posicion <= longitudCintaEjes) {
			return posicion;
		} else {
			return longitudCintaEjes;
		}
	}

	private float obtenerPosicionEje(long instante) {
		long instanteActual = System.currentTimeMillis();

		//Se calcula el tiempo total del eje/engranaje en la cinta en segundos
		float tiempoTotal = ((instanteActual - instante ) / 1000);

		// La velocidad de la cinta esta en metros/minuto
		float posicion = (velocidadCintaEjes * tiempoTotal) / 60;
		// la posicion se calcula a partir de la velocidad de la cinta y el tiempo que ha estado el eje/engranaje en la misma

		if (posicion <= longitudCintaEjes) {
			return posicion;
		} else {
			return longitudCintaEjes;
		}
	}

	/**
	 * Metodo que devuelve la posicion del engranaje en la cinta.
	 * 
	 * @return devuelve la posicion.
	 */
	private float obtenerPosicionEngranaje() {
		long instanteActual = System.currentTimeMillis();

		//Se calcula el tiempo total del eje/engranaje en la cinta en segundos
		float tiempoTotal = ((instanteActual - instanteInicialEngranaje ) / 1000);


		// La velocidad de la cinta esta en metros/minuto
		float posicion = (velocidadCintaEngranajes * tiempoTotal) / 60;
		// la posicion se calcula a partir de la velocidad de la cinta y el tiempo que ha estado el eje/engranaje en la misma

		if (posicion <= longitudCintaEngranajes) {
			return posicion;
		} else {
			return longitudCintaEngranajes;
		}
	}

	private float obtenerPosicionEngranaje(long instante) {
		long instanteActual = System.currentTimeMillis();

		//Se calcula el tiempo total del eje/engranaje en la cinta en segundos
		float tiempoTotal = ((instanteActual - instante ) / 1000);
		
		// La velocidad de la cinta esta en metros/minuto
		float posicion = (velocidadCintaEngranajes * tiempoTotal) / 60;
		// la posicion se calcula a partir de la velocidad de la cinta y el tiempo que ha estado el eje/engranaje en la misma

		if (posicion <= longitudCintaEngranajes) {
			return posicion;
		} else {
			return longitudCintaEngranajes;
		}
	}

	/**
	 * M&eacute;todo de transicion entre los diferentes estados de la cinta de ejes
	 */
	private void transitarCintaEjes() {
		boolean reconocidoSensorEjes=false;
		switch (estadoActualCintaEjes) {

			case 1:// Cintas de alimentacion paradas (Automata parado) (estado 1)

				if(paradaNormalInicio && conjuntosHechos%4==0){
					System.out.println("Parada normal y ejes/engranajes multiplo de 4");
				}else{
					if (primerRun) {
						//volverAInicializar();
						primerRun = false;
						estadoActualCintaEjes = 1;
					} else {
						estadoActualCintaEjes= 2;
					}
					estadoActualCintaEjes=2;
					EjeEnCinta = true;
					cintaEjesActivada = true;

					instanteInicialEje = System.currentTimeMillis();

					System.out.println("Nuevo eje en cinta");

					posicionesEjes.add(0f);
					instanteEjes.add(instanteInicialEje);
				}
				break;

			case 2:// Esperando a que el eje llegue al sensor
				primerRun = true;
				if(!paradaNormalInicio&&(posicionesEjes.size()<=capacidadEjes)){
					posicionesEjes.add(0f);
					instanteEjes.add(System.currentTimeMillis());
					System.out.println("Nuevo eje en cinta");
				}else{
					if((diferenciaEjes>0)){
						posicionesEjes.add(0f);
						instanteEjes.add(System.currentTimeMillis());
						System.out.println("Nuevo eje en cinta tras parada normal");
						diferenciaEjes--;
					}
				}
				for(int i=0;i<posicionesEjes.size();i++){
					posicionesEjes.set(i,obtenerPosicionEje(instanteEjes.get(i)));
				}
				if(posicionesEjes.size()!=0){
					posicionActualEje = obtenerPosicionEje(instanteEjes.get(0));
					reconocidoSensorEjes = estaEjeSensor(
							posicionActualEje,longitudCintaEjes);
				}
				if (reconocidoSensorEjes) {
					sensorCintaEjes = true;
					cintaEjesActivada=false;
					estadoActualCintaEjes=3;
					_logger.info("Eje en deposito final");
					/*posicionesEjes.remove(0);
					instanteEjes.remove(0);
					ejesRestante--;*/
				}


				break;

			case 3:/* El eje llega al final de la cinta, y es recogido por el robot 1 */
				//System.out.println("Eje en deposito final");
				if(estadoActualRobot1 == 0) {
					if (!robot1.tieneEje) {
						ejesRestante--;
						sensorCintaEjes = false;
						posicionesEjes.remove(0);
						instanteEjes.remove(0);
						robot1.tieneEje = true;
					}
				}

				//robot1.recogerEje();
				//System.out.println("Robot 1 recoge eje en cinta");

				break;
		}
	}

	/*private void transitarCintaEjes2() {
		//mensajeEstadoActual = "11";
		//System.out.println("Conjuntos hechos: "+conjuntosHechos);
		boolean reconocidoSensorEjes=false;
		switch (estadoActualCintaEjes) {

			case 1: // Cintas de alimentacion paradas (Automata parado) (estado 1)

				if(paradaNormalInicio && conjuntosHechos%4==0){
					System.out.println("Parada normal y ejes/engranajes multiplo de 4");
				}else{
					if (primerRun) {
						//volverAInicializar();
						primerRun = false;
						estadoActualCintaEjes = 1;
					} else {
						estadoActualCintaEjes= 2;
					}
					estadoActualCintaEjes=2;
					EjeEnCinta = true;
					cintaEjesActivada = true;

					instanteInicialEje = System.currentTimeMillis();

					System.out.println("Nuevo eje en cinta");

					posicionesEjes.add(0f);
					instanteEjes.add(instanteInicialEje);
				}
				break;

			case 2: // Esperando a que el eje llegue al sensor

				primerRun = true;
				if(!paradaNormalInicio&&(posicionesEjes.size()<=capacidadEjes)){
					posicionesEjes.add(0f);
					instanteEjes.add(System.currentTimeMillis());
					System.out.println("Nuevo eje en cinta");

				}else{
					if((diferenciaEjes>0)){
						posicionesEjes.add(0f);
						instanteEjes.add(System.currentTimeMillis());
						System.out.println("Nuevo eje en cinta tras parada normal");
						diferenciaEjes--;
					}
				}
				for(int i=0;i<posicionesEjes.size();i++){
					posicionesEjes.set(i,obtenerPosicionEje(instanteEjes.get(i)));
				}
				if(posicionesEjes.size()!=0){
					posicionActualEje = obtenerPosicionEje(instanteEjes.get(0));
					reconocidoSensorEjes = estaEjeSensor(
							posicionActualEje,longitudCintaEjes);
				}
				if (reconocidoSensorEjes) {
					cintaEjesActivada=false;
					estadoActualCintaEjes=3;
					posicionesEjes.remove(0);
					instanteEjes.remove(0);
					System.out.println("Eje en deposito final");
					//System.out.println("Robot 1 recoge eje en cinta");
				}


				break;

			case 3: // El eje llega al final de la cinta, y es recogido por el robot 1
				//System.out.println("Eje en deposito final");
				sensorCintaEjes=true;
				ejesRestante--;

				//robot1.recogerEje();
				//System.out.println("Robot 1 recoge eje en cinta");

				break;
		}
	}*/

	/**
	 * Comprueba si el eje/engranaje es detectado por el sensor
	 */
	private boolean estaEjeSensor(float posicionEje, float posicionSensor) {

		boolean enSensor = false;

		float umbral = (float) (this.longitudCintaEjes * 0.05);

		if ((posicionEje >= (posicionSensor - umbral))) {
			enSensor = true;
		}

		return enSensor;
	}


	/**
	 * M&eacute;todo de transicion entre los diferentes estados de la cinta de engranajes
	 */
	private void transitarCintaEngranajes() {
		//System.out.println("Conjuntos hechos: "+conjuntosHechos);
		boolean reconocidoSensorEngranajes=false;
		switch (estadoActualCintaEngranajes) {

			case 1:/* Cintas de alimentacion paradas (Automata parado) (estado 1) */

				if(paradaNormalInicio && conjuntosHechos%4==0){
					System.out.println("Parada normal y ejes/engranajes multiplo de 4");
				}else{
					if (primerRun) {
						//volverAInicializar();
						primerRun = false;
						estadoActualCintaEngranajes = 1;
					} else {
						estadoActualCintaEngranajes= 2;
					}
					estadoActualCintaEngranajes=2;
					EngranajeEnCinta = true;
					cintaEngranajesActivada = true;

					instanteInicialEngranaje = System.currentTimeMillis();
					posicionesEngranajes.add(0f);
					instanteEngranajes.add(System.currentTimeMillis());

					System.out.println("Nuevo engranaje en cinta");


				}
				break;

			case 2:/* Esperando a que el engranje llegue al sensor */

				primerRun = true;
				if(!paradaNormalInicio&&posicionesEngranajes.size()<=capacidadEngranajes){
					posicionesEngranajes.add(0f);
					instanteEngranajes.add(System.currentTimeMillis());
					System.out.println("Nuevo engranaje en cinta");

				}else{
					if((diferenciaEngranajes>0)){
						posicionesEngranajes.add(0f);
						instanteEngranajes.add(System.currentTimeMillis());
						System.out.println("Nuevo engranaje en cinta tras parada normal");
						diferenciaEngranajes--;
					}
				}
				for(int i=0;i<posicionesEngranajes.size();i++){
					posicionesEngranajes.set(i,obtenerPosicionEje(instanteEngranajes.get(i)));
				}
				if(posicionesEngranajes.size()!=0){
					posicionActualEngranaje = obtenerPosicionEngranaje(instanteEngranajes.get(0));
					reconocidoSensorEngranajes = estaEngranajeSensor(
							posicionActualEngranaje,longitudCintaEngranajes);
				}

				if (reconocidoSensorEngranajes) {
					cintaEngranajesActivada=false;
					estadoActualCintaEngranajes=3;
					/*posicionesEngranajes.remove(0);
					instanteEngranajes.remove(0);
					engranajesRestante--;*/
					_logger.info("Engranaje en deposito final");
					//System.out.println("Robot 1 recoge engranaje en cinta");
					sensorCintaEngranajes=true;
				}


				break;

			case 3:/* El engranaje llega al final de la cinta, y es recogido por el robot 1 */
				//System.out.println("Engranaje en deposito final");
				if(estadoActualRobot1 == 0) {
					if(!robot1.tieneEngranaje) {
						sensorCintaEngranajes=false;
						engranajesRestante--;
						posicionesEngranajes.remove(0);
						instanteEngranajes.remove(0);
						robot1.tieneEngranaje = true;
					}
				}

				//robot1.recogerEngranaje();
				//System.out.println("robot 1 recoge engranje");

		}
	}

	/*private void transitarCintaEngranajes2() {
		//System.out.println("Conjuntos hechos: "+conjuntosHechos);
		boolean reconocidoSensorEngranajes=false;
		switch (estadoActualCintaEngranajes) {

			case 1:// Cintas de alimentacion paradas (Automata parado) (estado 1)

				if(paradaNormalInicio && conjuntosHechos%4==0){
					System.out.println("Parada normal y ejes/engranajes multiplo de 4");
				}else{
					if (primerRun) {
						//volverAInicializar();
						primerRun = false;
						estadoActualCintaEngranajes = 1;
					} else {
						estadoActualCintaEngranajes= 2;
					}
					estadoActualCintaEngranajes=2;
					EngranajeEnCinta = true;
					cintaEngranajesActivada = true;

					instanteInicialEngranaje = System.currentTimeMillis();
					posicionesEngranajes.add(0f);
					instanteEngranajes.add(System.currentTimeMillis());

					System.out.println("Nuevo engranaje en cinta");
				}
				break;

			case 2:// Esperando a que el engranje llegue al sensor
				primerRun = true;
				if(!paradaNormalInicio&&insertarEjeEngranaje){
					posicionesEngranajes.add(0f);
					instanteEngranajes.add(System.currentTimeMillis());
					System.out.println("Nuevo engranaje en cinta");

				}else{
					if((diferenciaEngranajes>0)){
						posicionesEngranajes.add(0f);
						instanteEngranajes.add(System.currentTimeMillis());
						System.out.println("Nuevo engranaje en cinta");
						diferenciaEngranajes--;
					}
				}
				for(int i=0;i<posicionesEngranajes.size();i++){
					posicionesEngranajes.set(i,obtenerPosicionEje(instanteEngranajes.get(i)));
				}
				if(posicionesEngranajes.size()!=0){
					posicionActualEngranaje = obtenerPosicionEngranaje(instanteEngranajes.get(0));
					reconocidoSensorEngranajes = estaEngranajeSensor(
							posicionActualEngranaje,longitudCintaEngranajes);
				}

				if (reconocidoSensorEngranajes) {
					cintaEngranajesActivada=false;
					estadoActualCintaEngranajes=3;
					posicionesEngranajes.remove(0);
					instanteEngranajes.remove(0);
					System.out.println("Engranaje en deposito final");
					//System.out.println("Robot 1 recoge engranaje en cinta");
				}
				break;

			case 3:// El engranaje llega al final de la cinta, y es recogido por el robot 1
				//System.out.println("Engranaje en deposito final");
				sensorCintaEngranajes=true;
				engranajesRestante--;
				//robot1.recogerEngranaje();
				//System.out.println("robot 1 recoge engranje");

		}
	}*/

	/* Comprueba si el engranaje es detectado por el sensor
	 * 
	 * 
	 */
	private boolean estaEngranajeSensor(float posicionEngranaje, float posicionSensor) {

		boolean enSensor = false;

		float umbral = (float) (this.longitudCintaEngranajes * 0.05);

		if ((posicionEngranaje >= (posicionSensor - umbral))) {
			enSensor = true;
		}

		return enSensor;
	}

	private void transitarEstacionMontaje(){

		switch (estadoActualEstacionMontaje) {
			case 1://eje y engranaje en estacion
				if(!sensorPresenciaEstacionMontaje){
					estadoActualRobot1=0;
					conjuntoMontadoFinalizado = false;
					robot1.tieneEje=false;
					robot1.tieneEngranaje=false;
					estadoActualEstacionMontaje=2;
					ejeEnEstacion=true;
					engranajeEnEstacion=true;
					sensorPresenciaEstacionMontaje=true;
				}
				break;
			case 2://Eje y engranaje se montan
				if(!accionamientoHidraulicoActivado){
					accionamientoHidraulicoActivado=true;

					tiempoInicioMontaje = System.currentTimeMillis();
					int tiempoBucleEspera = (int)tiempoDeMontaje;
					enviarMensaje(MessageTypes.COMIENZO_MONTAJE,null);

					while (tiempoBucleEspera >= 0) {
						try {
							Thread.sleep(cicloReloj);
							tiempoBucleEspera = (int) (tiempoBucleEspera - cicloReloj);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					enviarMensaje(MessageTypes.FIN_MONTAJE,null);

					System.out.println("Conjunto Montado");

					System.out.println("Estacion disponible de nuevo");

					tiempoParadoMontaje = System.currentTimeMillis()- tiempoInicioMontaje;

					estadoActualEstacionMontaje = 3;
				}
				break;

			case 3:// se recoge el conjunto montado
				accionamientoHidraulicoActivado=false;
				ejeEnEstacion=false;
				engranajeEnEstacion=false;
				sensorPresenciaEstacionMontaje=false;
				conjuntoMontadoFinalizado = true;
				conjuntosHechos++;
				conjuntosPendientesParadaNormal--;

				//if(robot1.disponible()){
				if(estadoActualRobot1 == 0){
					estadoActualRobot1=2;
					enviarMensaje(MessageTypes.COMIENZO_ROBOT1_TRASLADO_CONJUNTO,null);
					robot1.recogerEnsamblado();
					estadoActualRobot1 = 0;
				}
				HashMap<String, String> estados=new HashMap<String, String>();

				estados.put("conjuntoDisponible", "true");

				enviarMensaje(MessageTypes.CONJUNTO_MONTADO_DISPONIBLE,estados);
				System.out.println("MENSAJE FINAL ENVIADO");
				estadoActualEstacionMontaje=1;
				transitarEstacion=false;
				break;
		}
	}

	/*private void transitarEstacionMontaje2(){

		switch (estadoActualEstacionMontaje) {
			case 1://eje y engranaje en estacion

				if(!sensorPresenciaEstacionMontaje){

					estadoActualRobot1=0;
					conjuntoMontadoFinalizado = false;
					robot1.tieneEje=false;
					robot1.tieneEngranaje=false;
					estadoActualEstacionMontaje=2;
					ejeEnEstacion=true;
					engranajeEnEstacion=true;
					sensorPresenciaEstacionMontaje=true;
					//System.out.println("llega un eje y engranaje a estacion");
				}
				break;
			case 2://Eje y engranaje se montan

				if(!accionamientoHidraulicoActivado){

					accionamientoHidraulicoActivado=true;

					tiempoInicioMontaje = System.currentTimeMillis();
					int tiempoBucleEspera = (int)tiempoDeMontaje;
					while (tiempoBucleEspera >= 0) {
						try {
							Thread.sleep(cicloReloj);
							tiempoBucleEspera = (int) (tiempoBucleEspera - cicloReloj);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}

					System.out.println("Conjunto Montado");

					System.out.println("Estacion disponible de nuevo");

					tiempoParadoMontaje = System.currentTimeMillis()- tiempoInicioMontaje;

					estadoActualEstacionMontaje = 3;
				}
				break;

			case 3:// se recoge el conjunto montado
				accionamientoHidraulicoActivado=false;
				ejeEnEstacion=false;
				engranajeEnEstacion=false;
				sensorPresenciaEstacionMontaje=false;
				conjuntoMontadoFinalizado = true;
				conjuntosHechos++;
				conjuntosPendientesParadaNormal--;

				if(estadoActualRobot1==0){
					estadoActualRobot1=2;
					robot1.recogerEnsamblado();
					estadoActualEstacionMontaje=1;
					transitarEstacion=false;
				}	


				System.out.println("MENSAJE FINAL ENVIADO");



				break;
		}
	}*/


	/**
	 * Metodo que gestiona y coordina todo el funcionamiento del automata 1
	 * @throws RemoteException 
	 * @throws InterruptedException 
	 */	
	public void gestionar() throws RemoteException, InterruptedException{
		long instanteInicialAutomata = 0;
		int i=0;
		int contadorCiclos=0;
		boolean emergencia=false;
		boolean primeraNormal=false;
		//boolean finBuscarMensaje=false;
		Mensaje mensajeRecibido=new Mensaje();
		//Mensaje parada=new Mensaje();
		//cicloReloj=600;
		while(true){
			if(!_miBuzon.isEmpty()) {
				mensajeRecibido=recibirMensaje();
				switch(mensajeRecibido.get_type()){

					case START:	
						this.inicializar();
						automataArrancado=true;
						emergencia=false;
						instanteInicialAutomata = System.currentTimeMillis();

						this.configurar(mensajeRecibido.get_message());
						robot1.configurar(mensajeRecibido.get_message());

						paradaNormalInicio=false;
						paradaNormalFin=false;
						conjuntosPendientesParadaNormal=0;
						System.out.println("START");
						//finBuscarMensaje=true;
						break;
						
					case STOP:
						paradaNormalInicio=true;
						primeraNormal=true;
						System.out.println("STOP");
						//finBuscarMensaje=true;
						break;
						
					case EMERGENCY_STOP:
						emergencia=true;
						System.out.println("EMERGENCY_STOP");
						//finBuscarMensaje=true;
						break;
						
					default:
						break;

				}
			}


			if(!emergencia) {
				if (automataArrancado && !paradaNormalFin) {
					// Si el eje/engranaje esta en la cinta y la cinta esta en marcha
					if ((EjeEnCinta && cintaEjesActivada) && (EngranajeEnCinta && cintaEngranajesActivada)) {
						posicionActualEje = obtenerPosicionEje();
						_logger.fine("Posicion actual del eje "+posicionActualEje);
						posicionActualEngranaje = obtenerPosicionEngranaje();
						_logger.fine("Posicion actual del engranaje "+posicionActualEngranaje);
					}

					//System.out.println(posicionesEjes.size());
					
					if(paradaNormalInicio && primeraNormal){
						if(posicionesEjes.size()>posicionesEngranajes.size()){
							conjuntosPendientesParadaNormal = posicionesEjes.size();
							diferenciaEngranajes = posicionesEjes.size()-posicionesEngranajes.size();
						}else{
							conjuntosPendientesParadaNormal = posicionesEngranajes.size();
							diferenciaEjes = posicionesEngranajes.size()-posicionesEjes.size();
						}
						primeraNormal = false;
						conjuntosSoltadosParadaNormal = conjuntosHechos;
					}

					insertarEjeEngranaje=false;
					contadorCiclos++;
					_logger.fine("Contador de ciclos "+contadorCiclos);
					if(contadorCiclos==4){
						insertarEjeEngranaje=true;
						contadorCiclos=0;
					}
					// Si no han pulsado parada de emergencia el automata sigue funcionando
					transitarCintaEjes();
					transitarCintaEngranajes();

					if(robot1.tieneEje && robot1.tieneEngranaje){
						HashMap<String, String> estados=new HashMap<String, String>();
						estados.put("estadoCintaEjes", Integer.toString(estadoActualCintaEjes));
						estados.put("estadoCintaEngranajes", Integer.toString(estadoActualCintaEngranajes));
						estados.put("estadoCintaEstacionMontaje", Integer.toString(estadoActualEstacionMontaje));
						estados.put("ejesEnCinta", Integer.toString(posicionesEjes.size()));
						estados.put("engranajesEnCinta", Integer.toString(posicionesEngranajes.size()));
						
						enviarMensaje(MessageTypes.ESTADOS1,estados);
						Thread.sleep(500);//PARA QUE SE VEA LA LUCECITA ROJA EN LA INERFAZ
						if(!transitarEstacion){
							estadoActualRobot1=1;
							enviarMensaje(MessageTypes.COMIENZO_ROBOT1_TRASLADO_EJE_ENGRANAJE, null);
							// Chumo: esto tambien tiene pone tieneEje y tieneEngranaje a false
							robot1.recogerEjeEngranaje();
							enviarMensaje(MessageTypes.FIN_ROBOT1_TRASLADO_EJE_ENGRANAJE, null);
							estadoActualRobot1 = 0;
						} else{
							_logger.info("Estacion de montaje ocupada");
						}

						transitarEstacion = true;
						estadoActualCintaEjes=2;
						estadoActualCintaEngranajes=2;
					}

					if(transitarEstacion){
						transitarEstacionMontaje();
					}

					if(conjuntosPendientesParadaNormal+conjuntosSoltadosParadaNormal==conjuntosHechos&&conjuntosHechos!=0){
						paradaNormalFin=true;
					}

					/*long instanteFinalAutomata = System.currentTimeMillis();
				long tiempoEsperaAUT1 = cicloReloj - (instanteFinalAutomata - instanteInicialAutomata);*/
					long tiempoEsperaAUT1 = cicloReloj;
					try {
						if (tiempoEsperaAUT1 >= 0)
							Thread.sleep(tiempoEsperaAUT1);
						else
							_logger.warning("El sistema tiene un ciclo de reloj muy bajo");
					} catch (InterruptedException e) {
						_logger.log(Level.SEVERE, "", e.getStackTrace());
					}
					i++;
					HashMap<String, String> estados=new HashMap<String, String>();
					estados.put("estadoCintaEjes", Integer.toString(estadoActualCintaEjes));
					estados.put("estadoCintaEngranajes", Integer.toString(estadoActualCintaEngranajes));
					estados.put("estadoCintaEstacionMontaje", Integer.toString(estadoActualEstacionMontaje));
					estados.put("ejesEnCinta", Integer.toString(posicionesEjes.size()));
					estados.put("engranajesEnCinta", Integer.toString(posicionesEngranajes.size()));

					enviarMensaje(MessageTypes.ESTADOS1,estados);
					_logger.info("enviando mensaje estados1...");
				}else{
					try {
						Thread.sleep(cicloReloj);
						_logger.fine("Esperando arranque...");
					} catch (InterruptedException e) {
						_logger.log(Level.SEVERE, "", e.getStackTrace());
					}
				}
			} else {
				try {
					Thread.sleep(cicloReloj);
					_logger.fine("Esperando arranque...");
				} catch (InterruptedException e) {
					_logger.log(Level.SEVERE, "", e.getStackTrace());
				}
			}
			
			_logger.info("Conjuntos hechos: "+conjuntosHechos);
			System.out.println("*****************************");
		}
	}

	/*public void gestionarPrueba(){

		long instanteInicialAutomata = 0;
		int i=0;
		int cont=0;
		int leido=0;

		boolean automataArrancado=true;
		boolean emergencia=false;
		boolean primeraNormal=false;
		Mensaje mensajeRecibido=new Mensaje();
		Mensaje parada=new Mensaje();
		estadoActualRobot1=0;
		cicloReloj=500;
		int contadorCiclos=0;
		while(true){

			insertarEjeEngranaje=false;
			contadorCiclos++;
			instanteInicialAutomata = System.currentTimeMillis();

			if(posicionesEjes.size()==9&&cont==0){
				try{
					leido=System.in.read();
				}catch(Exception e){}
				if(leido==49){
					cont++;
					paradaNormalInicio=true;
					primeraNormal=true;
				}
			}

			if(!emergencia){


				/ *if(inicioArranque.get_message().get
					("arranque").equals("true")&&!paradaNormalFin){* /


				if (automataArrancado&&!paradaNormalFin) {

					if ((EjeEnCinta && cintaEjesActivada)&&(EngranajeEnCinta && cintaEngranajesActivada)) {// Si el eje/engranaje esta en la cinta y la cinta esta en marcha
						posicionActualEje = obtenerPosicionEje();
						System.out.println(posicionActualEje);
						posicionActualEngranaje = obtenerPosicionEngranaje();
						System.out.println(posicionActualEngranaje);
					}
					System.out.println(posicionesEjes.size());
					if(paradaNormalInicio&&primeraNormal){
						if(posicionesEjes.size()>posicionesEngranajes.size()){
							conjuntosPendientesParadaNormal=posicionesEjes.size();
							diferenciaEngranajes=posicionesEjes.size()-posicionesEngranajes.size();
						}else{
							conjuntosPendientesParadaNormal=posicionesEngranajes.size();
							diferenciaEjes=posicionesEngranajes.size()-posicionesEjes.size();
						}
						primeraNormal=false;
						conjuntosSoltadosParadaNormal=conjuntosHechos;
					}

					if(contadorCiclos==4){
						insertarEjeEngranaje=true;
						contadorCiclos=0;
					}
					//if(estadoActualCintaEjes!=3)
					transitarCintaEjes2();// Si no han pulsado parada de emergencia el automata sigue funcionando
					//if(estadoActualCintaEngranajes!=3)
					transitarCintaEngranajes2();

					if(estadoActualCintaEjes==3&&estadoActualCintaEngranajes==3){

						if(!transitarEstacion){
							estadoActualRobot1=1;
							robot1.recogerEjeEngranaje();
							transitarEstacion=true;
							estadoActualCintaEjes=2;
							estadoActualCintaEngranajes=2;

						}else{
							System.out.println("estacion ocupada");
						}



					}

					if(transitarEstacion){

						transitarEstacionMontaje2();

					}

					if(conjuntosPendientesParadaNormal+conjuntosSoltadosParadaNormal==conjuntosHechos&&conjuntosHechos!=0){
						paradaNormalFin=true;
					}






					long instanteFinalAutomata = System.currentTimeMillis();
					long tiempoEsperaAUT1 = cicloReloj - (instanteFinalAutomata - instanteInicialAutomata);
					//long tiempoEsperaAUT1 = cicloReloj;
					try {
						if (tiempoEsperaAUT1 >= 0)
							Thread.sleep(tiempoEsperaAUT1);
						else
							System.out.println("El sistema tiene un ciclo de reloj muy bajo");
					} catch (InterruptedException e) {
						System.out.println("Se ha producido un error al dormir el Automata1 "	+ e);
						e.printStackTrace();
					}
					i++;

					System.out.println("enviando mensaje estados1...");
				}else{
					try {
						Thread.sleep(cicloReloj);
						System.out.println("Esperando arranque...");
					} catch (InterruptedException e) {
						System.out.println("Se ha producido un error al dormir el Automata1 "	+ e);
						e.printStackTrace();
					}
				}
			}else{
				try {
					Thread.sleep(cicloReloj);
					System.out.println("Esperando arranque...");
				} catch (InterruptedException e) {
					System.out.println("Se ha producido un error al dormir el Automata1 "	+ e);
					e.printStackTrace();
				}
			}
			System.out.println("*****************************");	
		}


	}*/

	public static void main(String[] args) throws Exception{


		Automata1 automata=new Automata1();
		automata.gestionar();


		/*
		Automata1 au=new Automata1();
		HashMap<String, String> param=new HashMap<String, String>();
		param.put("cicloReloj", "1000");
		param.put("velocidadEjes", "40");
		param.put("longitudEjes", "10");
		param.put("capacidadEjes", "50");
		param.put("velocidadEngranajes", "40");
		param.put("longitudEngranajes", "10");
		param.put("capacidadEngranajes", "50");
		param.put("tiempoMontaje", "3000");
		au.configurar(param);

		System.out.println(au.cicloReloj);
		 */




		/*
		Automata1 au=new Automata1(true);
		au.gestionarPrueba();
		 */

	}

}
